package algorithms;

import java.util.ArrayList;

import templates.Operator;
import templates.State;

public class LDepthSearch<Template> extends Algorithm<Template>{
	public LDepthSearch(State<Template> iState,
			ArrayList<State<Template>> fStates,
			ArrayList<Operator<Template>> opr, String log) {
		super(iState, fStates, opr, log);
	}
	private boolean switcher ;
	private Operator<Template> last;
	private int maxDepth;
	private int currentDepth;
	private boolean result= false;
	private boolean finished= false;

	

	private boolean expand(State<Template> thisState)
	{
		int counter=0;
		if ( isSwitcher()){
		counter=getIndex(thisState.getRedoOperator())+1; setSwitcher(false); }
		if (getIndex(thisState.getCurrentOperator())==operatorNumber) { if(OTest())finished=true; last=btStack.peek().getRedoOperator(); counter=0; }
		for(int i=counter;i<=operatorNumber;i++)
		{
			if (operators.get(i).available(thisState.getCurrentState())) 
				{
					State<Template> auxiliary=new State<Template>(operators.get(i).execute(thisState.getCurrentState()), operators.get(i));
					if (!found(auxiliary)) { btStack.push(auxiliary); currentDepth++; return true;}
				}
		}
		return false;
	}
	
	private boolean OTest() {
		if (last!=null)
		if (last.equals(btStack.peek().getRedoOperator()))
		{
		return true;
		}

		return false;
	}



	private boolean solve(State<Template> thisState)
	{
		
		if( !isSwitcher()) setSwitcher(false);
		if( thisState!=null && finished==false ){
		if(expand(thisState) && currentDepth<=maxDepth)
		{
			if ( solutionFound( btStack.peek() )) {result=true; return true;} ;
		}else 
			{ 
				Operator<Template> auxiliaryOperator=btStack.peek().getCurrentOperator();				
				if (btStack.size()>1)
				btStack.pop();
				State<Template> auxiliaryState=btStack.pop();
				auxiliaryState.setRedoOperator(auxiliaryOperator);
				btStack.push(auxiliaryState);
				setSwitcher(true);
				currentDepth--;				
			}	
		solve(btStack.peek());
		}
		return false;
	}


	private boolean setSwitcher(boolean switcher) {
		this.switcher = switcher;
		return switcher;
	}

	public boolean isSwitcher() {
		return switcher;
	}

	public boolean solveProblem() {
		result=false;
		solve(initialState);
		if (result==true) return true;
		return false;
		
	}
	public void init()
	{
		currentDepth=1;
		setSwitcher(false);
	}

	public void setMaxDepth(int maxDepth) {
		this.maxDepth = maxDepth;
	}

	public int getMaxDepth() {
		return maxDepth;
	}	

}
